#include "stdio.h"
#include"cpu.h"

#include"bus.h"
#ifndef __GNUC__
#pragma warning(disable : 4700)
#endif

//A2.6.8 Interrupt request (IRQ) exception
//The IRQ exception is generated externally by asserting the IRQ input on the processor. It has a lower priority
//than FIQ (see Table A2-1 on page A2-25), and is masked out when an FIQ sequence is entered.
//Interrupts are disabled when the I bit in the CPSR is set. If the I bit is clear, ARM checks for an IRQ at
//instruction boundaries.
//Note
//The I bit can only be changed from a privileged mode.
//When an IRQ is detected, the following actions are performed:
//R14_irq = address of next instruction to be executed + 4
//SPSR_irq = CPSR
//CPSR[4:0] = 0b10010 /* Enter IRQ mode */
//CPSR[5] = 0 /* Execute in ARM state */
///* CPSR[6] is unchanged */
//CPSR[7] = 1 /* Disable normal interrupts */
//CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
//CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
//if VE==0 then
//if high vectors configured then
//PC = 0xFFFF0018
//else
//PC = 0x00000018
//else
//PC = IMPLEMENTATION DEFINED /* see page A2-26 */
//To return after servicing the interrupt, use:
//SUBS PC,R14,#4
//This restores both the PC (from R14_irq) and CPSR (from SPSR_irq), and resumes execution of the
//interrupted code.


void CCPU::exec_irq()
{
	regfile.prf[R14_IRQ]=regfile.prf[PC]+4;
	regfile.prf[SPSR_IRQ]=regfile.prf[CPSR];
	regfile.prf[CPSR]&=~0x1f;
	regfile.prf[CPSR]|=MODE_IRQ_VAL;
	regfile.mode=MODE_IRQ;
	CLR_BIT(regfile.prf[CPSR],CPSR_BIT_T);
	SET_BIT(regfile.prf[CPSR],CPSR_BIT_I);
	SET_BIT(regfile.prf[CPSR],CPSR_BIT_A);
	// bit 9
	if(mmu.cp15.ControlRegister().EE)
	{
		SET_BIT(regfile.prf[CPSR],CPSR_BIT_E);
	}
	else
	{
		CLR_BIT(regfile.prf[CPSR],CPSR_BIT_E);
	}

	if(mmu.cp15.ControlRegister().VE==0)
	{
		if(mmu.cp15.ControlRegister().V)
		
			regfile.prf[PC]=0xFFFF0018;
		else
			regfile.prf[PC]=0x18;
	}
	else
		//???
		;
}

//R14_und = address of next instruction after the Undefined instruction
//SPSR_und = CPSR
//CPSR[4:0] = 0b11011 /* Enter Undefined Instruction mode */
//CPSR[5] = 0 /* Execute in ARM state */
///* CPSR[6] is unchanged */
//CPSR[7] = 1 /* Disable normal interrupts */
///* CPSR[8] is unchanged */
//CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
//if high vectors configured then
//PC = 0xFFFF0004
//else
//PC = 0x00000004

//Undefined_Instruction_exception
void CCPU::exec_ud()
{
}




//R14_svc = address of next instruction after the SWI instruction
//SPSR_svc = CPSR
//CPSR[4:0] = 0b10011 /* Enter Supervisor mode */
//CPSR[5] = 0 /* Execute in ARM state */
///* CPSR[6] is unchanged */
//CPSR[7] = 1 /* Disable normal interrupts */
///* CPSR[8] is unchanged */
//CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
//if high vectors configured then
//PC = 0xFFFF0008
//else
//PC = 0x00000008
//To return after performing

void CCPU::exec_swi()
{
	regfile.mode=MODE_SVC;
	regfile.prf[R14_SVC]=regfile.prf[PC]+4;
	regfile.prf[SPSR_SVC]=regfile.prf[CPSR];
	regfile.prf[CPSR]&=~0x1f;
	regfile.prf[CPSR]|=MODE_SVC_VAL;
	regfile.mode=MODE_SVC;
	CLR_BIT(regfile.prf[CPSR],CPSR_BIT_T);
	SET_BIT(regfile.prf[CPSR],CPSR_BIT_I);
	if(mmu.cp15.ControlRegister().EE)
	{
		SET_BIT(regfile.prf[CPSR],CPSR_BIT_E);
	}
	else
	{
		CLR_BIT(regfile.prf[CPSR],CPSR_BIT_E);
	}

	if(mmu.cp15.ControlRegister().VE==0)
	{
		if(mmu.cp15.ControlRegister().V)
		
			regfile.prf[PC]=0xFFFF0008;
		else
			regfile.prf[PC]=0x8;
	}
	else
		//???
		;
}


//R14_abt = address of the aborted instruction + 4
//SPSR_abt = CPSR
//CPSR[4:0] = 0b10111 /* Enter Abort mode */
//CPSR[5] = 0 /* Execute in ARM state */
///* CPSR[6] is unchanged */
//CPSR[7] = 1 /* Disable normal interrupts */
//CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
//CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
//if high vectors configured then
//PC = 0xFFFF000C
//else
//PC = 0x0000000C

void CCPU::exec_prefetch_abort()
{
}


//R14_abt = address of the aborted instruction + 8
//SPSR_abt = CPSR
//CPSR[4:0] = 0b10111 /* Enter Abort mode */
//CPSR[5] = 0 /* Execute in ARM state */
///* CPSR[6] is unchanged */
//CPSR[7] = 1 /* Disable normal interrupts */
//CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
//CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
//if high vectors configured then
//PC = 0xFFFF0010
//else
//PC = 0x00000010
//To return after fixing the reason

void CCPU::exec_data_abort()
{
}

//R14_fiq = address of next instruction to be executed + 4
//SPSR_fiq = CPSR
//CPSR[4:0] = 0b10001 /* Enter FIQ mode */
//CPSR[5] = 0 /* Execute in ARM state */
//CPSR[6] = 1 /* Disable fast interrupts */
//CPSR[7] = 1 /* Disable normal interrupts */
//CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
//CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
//if VE==0 then
//if high vectors configured then
//PC = 0xFFFF001C
//else
//PC = 0x0000001C
//else
//PC = IMPLEMENTATION DEFINED /* see page A2-26 */

void CCPU::exec_fiq()
{
	regfile.prf[R14_FIQ]=regfile.prf[PC]+4;
	regfile.prf[SPSR_FIQ]=regfile.prf[CPSR];
	regfile.prf[CPSR]&=~0x1f;
	regfile.prf[CPSR]|=MODE_FIQ_VAL;
	regfile.mode=MODE_FIQ;
	CLR_BIT(regfile.prf[CPSR],CPSR_BIT_T);
	SET_BIT(regfile.prf[CPSR],CPSR_BIT_F);
	SET_BIT(regfile.prf[CPSR],CPSR_BIT_I);
	SET_BIT(regfile.prf[CPSR],CPSR_BIT_A);
	// bit 9
	if(mmu.cp15.ControlRegister().EE)
	{
		SET_BIT(regfile.prf[CPSR],CPSR_BIT_E);
	}
	else
	{
		CLR_BIT(regfile.prf[CPSR],CPSR_BIT_E);
	}

	if(mmu.cp15.ControlRegister().VE==0)
	{
		if(mmu.cp15.ControlRegister().V)
		
			regfile.prf[PC]=0xFFFF001C;
		else
			regfile.prf[PC]=0x1C;
	}
	else
		;
}

//if (not overridden by debug hardware)
//R14_abt = address of BKPT instruction + 4
//SPSR_abt = CPSR
//CPSR[4:0] = 0b10111 /* Enter Abort mode */
//CPSR[5] = 0 /* Execute in ARM state */
///* CPSR[6] is unchanged */
//CPSR[7] = 1 /* Disable normal interrupts */
//CPSR[8] = 1 /* Disable imprecise aborts - v6 only */
//CPSR[9] = CP15_reg1_EEbit
//if high vectors configured then
//PC = 0xFFFF000C
//else
//PC = 0x0000000C


void CCPU::exec_bkpt()
{
}



//R14_svc = UNPREDICTABLE value
//SPSR_svc = UNPREDICTABLE value
//CPSR[4:0] = 0b10011 /* Enter Supervisor mode */
//CPSR[5] = 0 /* Execute in ARM state */
//CPSR[6] = 1 /* Disable fast interrupts */
//CPSR[7] = 1 /* Disable normal interrupts */
//CPSR[8] = 1 /* Disable Imprecise Aborts (v6 only) */
//CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
//if high vectors configured then
//PC = 0xFFFF0000
//else
//PC = 0x00000000
void CCPU::reset()
{
	//memset(&state,0,sizeof(state));
	//state.mode=MODE_SVC;
	//regfile.prf[PC]=0x80000;
	regfile.reset();

	//regfile.prf[R14_SVC]=;
	//regfile.prf[SPSR_SVC]=;

	regfile.prf[R1]=0x793; // machine numberfor XIP calling
	mmu.cp15.reset();
}